﻿using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using Microsoft.WindowsAzure.ServiceRuntime;
using System.Diagnostics;

namespace Events.Data
{
	public partial class HelfenHelfenEntities
	{
		public static HelfenHelfenEntities Create()
		{
			var connectionString = string.Empty;
			if (RoleEnvironment.IsAvailable)
			{
				connectionString = RoleEnvironment.GetConfigurationSettingValue("ConnectionString");
			}
			else
			{
				connectionString = ConfigurationManager.ConnectionStrings["HelfenHelfenEntities"].ConnectionString;
			}

			return new HelfenHelfenEntities(connectionString);
		}

		public Guid RegisterAndSaveChanges(Guid demandId, string email)
		{
			var missionId = Guid.NewGuid();
			var requestedEvent = this.DemandDetails.Where(dd => dd.DemandDetailsGUID == demandId).FirstOrDefault();
			if (requestedEvent == null)
			{
				throw new ArgumentException("Unknonwn event id.", "demandId");
			}

			var user = this.UserDetails.Where(u => u.EMail == email).FirstOrDefault();
			if (user == null)
			{
				throw new RegistrationException("You are not a registered user of this platform!");
			}

			try
			{
				this.AddToMissions(new Mission()
					{
						MissionGUID = missionId,
						UserDetail = user,
						MissionState = this.MissionStates.FirstOrDefault(),
						DemandDetail = requestedEvent
					});
				this.SaveChanges();
			}
			catch (UpdateException ex)
			{
				missionId = Guid.Empty;
				var sqlException = ex.InnerException as SqlException;
				if (sqlException == null || !sqlException.Message.Contains("IX_Demand_User"))
				{
					throw;
				}
				else
				{
					throw new RegistrationException("You have already been registered for this event.");
				}
			}

			return missionId;
		}

		public void SendRegistrationConfirmation(Guid missionId)
		{
			Trace.WriteLine("Trying to create registration document");
			try
			{
				using (var docStream = this.CreateRegistrationConfirmation(missionId))
				{
					Trace.WriteLine("Successfully created registration document");
					TemplateManager.Create().SendRegistration(docStream, missionId);
				}
			}
			catch (Exception ex)
			{
				Trace.WriteLine(ex.Message);
				throw;
			}
		}

		public void QueueRegistrationMail(Guid missionId)
		{
			TemplateManager.Create().QueueRegistration(missionId);
		}

		private Stream CreateRegistrationConfirmation(Guid missionId)
		{
			var mission = this.Missions.Include("DemandDetail.Demand").Include("UserDetail").Where(m => m.MissionGUID == missionId).FirstOrDefault();
			if (mission == null)
			{
				throw new ArgumentException("Unknown mission id", "missionId");
			}

			var tempFileId = Guid.NewGuid();

			var tempPath = string.Empty;
			var templateManager = TemplateManager.Create();
			if (RoleEnvironment.IsAvailable)
			{
				tempPath = RoleEnvironment.GetLocalResource("TemporaryFiles").RootPath;
			}
			else
			{
				tempPath = @"C:\temp\azuretests";
			}

			var tempFileName = Path.Combine(tempPath, tempFileId.ToString());
			File.WriteAllBytes(tempFileName, templateManager.GetRegistrationConfirmationTemplate());
			try
			{
				using (var doc = WordprocessingDocument.Open(tempFileName, true))
				{
					var attendeeTable = doc.MainDocumentPart.Document.Body.Elements<Table>().First();

					Func<Table, int, Text> getCellText = (t, rowIndex) => t
						.Elements<TableRow>().ElementAt(rowIndex)
						.Elements<TableCell>().ElementAt(1)
						.Elements<Paragraph>().First()
						.Elements<Run>().First()
						.Elements<Text>().First();

					getCellText(attendeeTable, 0).Text = mission.UserDetail.FirstName;
					getCellText(attendeeTable, 1).Text = mission.UserDetail.Lastname;
					getCellText(attendeeTable, 2).Text = mission.UserDetail.EMail;
					getCellText(attendeeTable, 3).Text = mission.DemandDetail.Demand.Title;

					doc.MainDocumentPart.Document.Save();
				}

				return this.CopyFileToMemoryStream(tempFileName);
			}
			finally
			{
				File.Delete(tempFileName);
			}
		}

		private MemoryStream CopyFileToMemoryStream(string sourceFilePath)
		{
			using (var sourceDocStream = new FileStream(sourceFilePath, FileMode.Open))
			{
				var destStream = new MemoryStream((int)sourceDocStream.Length);
				try
				{
					sourceDocStream.CopyTo(destStream);
					destStream.Seek(0, SeekOrigin.Begin);
					return destStream;
				}
				catch
				{
					destStream.Dispose();
					throw;
				}
			}
		}
	}
}
